package org.darcy.service.org.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.darcy.entity.org.Company;
import org.darcy.entity.org.Department;
import org.darcy.entity.privilege.SysUser;
import org.darcy.framework.constant.SysConstant;
import org.darcy.framework.generic.GenericServiceImpl;
import org.darcy.framework.model.PageData;
import org.darcy.framework.model.PageParam;
import org.darcy.service.org.CompanyService;
import org.darcy.service.org.OrgDepartmentService;
import org.darcy.utils.common.ReturnCode;
import org.darcy.utils.vo.ReturnVo;
import org.darcy.vo.org.OrgTreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

@Service
public class CompanyServiceImpl extends GenericServiceImpl<Company> implements CompanyService {

	@Lazy
	@Autowired
	private OrgDepartmentService departmentService;

	@Override
	public PageData<Company> page(PageParam<Company> param) {
		IPage<Company> queryPage = new Page<Company>(param.getQuery().getPageNum(), param.getQuery().getPageSize());
		LambdaQueryWrapper<Company> params = new LambdaQueryWrapper<Company>();
		String name = StringUtils.trim(param.getEntity().getCname());
		if (StringUtils.isNotBlank(name)) {
			params.like(Company::getCode, name).or().like(Company::getEname, name).or().like(Company::getShortName,
					name);
		}
		IPage<Company> page = this.getPage(queryPage, params);
		PageData<Company> pageData = new PageData<Company>(page, param);
		return pageData;
	}

	@Override
	public List<Company> list(Company param) {
		LambdaQueryWrapper<Company> params = new LambdaQueryWrapper<Company>();
		String name = StringUtils.trim(param.getCname());
		if (StringUtils.isNotBlank(name)) {
			params.like(Company::getCode, name).or().like(Company::getEname, name).or().like(Company::getShortName,
					name);
		}
		List<Company> list = this.getList(params);
		return list;
	}

	@Override
	public Company getCompanyByCode(String code) {
		if (StringUtils.isNotBlank(code)) {
			LambdaQueryWrapper<Company> companyLambdaQueryWrapper = new LambdaQueryWrapper<>();
			companyLambdaQueryWrapper.eq(Company::getCode, code).eq(Company::getDelFlag, SysConstant.DEL_FLAG_1);
			return this.getOne(companyLambdaQueryWrapper);
		}
		return null;
	}

	@Override
	public ReturnVo<String> importCompany(List<Company> companies, SysUser loginUser) {
		ReturnVo<String> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK");
		if (CollectionUtils.isNotEmpty(companies)) {
			List<String> codes = new ArrayList<>();
			companies.forEach(company -> codes.add(company.getCode()));
			if (CollectionUtils.isNotEmpty(codes)) {
				LambdaQueryWrapper<Company> companyLambdaQueryWrapper = new LambdaQueryWrapper<>();
				companyLambdaQueryWrapper.in(Company::getCode, codes);
				List<Company> oldDbCompanies = this.getList(companyLambdaQueryWrapper);
				Map<String, Company> oldDbCompanyMap = oldDbCompanies.stream()
						.collect(Collectors.toMap(Company::getCode, company -> company));
				List<Company> oldCompanies = new ArrayList<>();
				List<Company> newCompanies = new ArrayList<>();
				if (CollectionUtils.isNotEmpty(companies)) {
					companies.forEach(company -> {
						if (!oldDbCompanyMap.containsKey(company.getCode())) {
							newCompanies.add(company);
						} else {
							oldCompanies.add(company);
						}
					});
				}
				Map<String, Company> oldCompanyMap = oldCompanies.stream()
						.collect(Collectors.toMap(Company::getCode, company -> company));
				oldDbCompanies.forEach(company -> {
					Company newCompany = oldCompanyMap.get(company.getCode());
					convert(company, newCompany);
				});
				List<Company> saveOrUpdateBatch = new ArrayList<>();
				saveOrUpdateBatch.addAll(newCompanies);
				saveOrUpdateBatch.addAll(oldDbCompanies);
				Map<String, Company> saveOrUpdateBatchMap = saveOrUpdateBatch.stream()
						.collect(Collectors.toMap(Company::getCode, company -> company));
				saveOrUpdateBatch.forEach(company -> {
					if (StringUtils.isNotBlank(company.getPcode())) {
						company.setPid(saveOrUpdateBatchMap.get(company.getPcode()).getId());
					}

				});
				this.updateBatch(saveOrUpdateBatch);
			}
		}
		return returnVo;
	}

	// 转化公司
	void convert(Company oldCompany, Company newCompany) {
		if (oldCompany != null && newCompany != null) {
			oldCompany.setCode(newCompany.getCode());
			oldCompany.setPcode(newCompany.getPcode());
			oldCompany.setCname(newCompany.getCname());
			oldCompany.setEname(newCompany.getEname());
			oldCompany.setDescr(newCompany.getDescr());
			oldCompany.setShortName(newCompany.getShortName());
		}
	}

	@Override
	public void getAllCompanyIds(Integer id, List<Integer> ids) {
		if (ids == null) {
			ids = new ArrayList<>();
		}
		ids.add(id);
		LambdaQueryWrapper<Company> companyLambdaQueryWrapper = new LambdaQueryWrapper<>();
		companyLambdaQueryWrapper.eq(Company::getPid, id).eq(Company::getDelFlag, SysConstant.DEL_FLAG_1);
		long count = this.count(companyLambdaQueryWrapper);
		if (count > 0) {
			List<Company> companyList = this.getList(companyLambdaQueryWrapper);
			List<Integer> finalIds = ids;
			companyList.forEach(company -> this.getAllCompanyIds(company.getId(), finalIds));
		} else {
			return;
		}
	}

	@Override
	public void saveOrUpdate(Company company, SysUser loginUser) {
		if (company.getId() != null) {
			this.update(company);
		} else {
			this.insert(company);
		}
	}

	@Override
	public ReturnVo<String> deleteByIds(List<String> ids) {
		ReturnVo<String> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK");
		LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
		departmentLambdaQueryWrapper.in(Department::getCompanyId, ids).eq(Department::getDelFlag,
				SysConstant.DEL_FLAG_1);
		long count = departmentService.count(departmentLambdaQueryWrapper);
		if (count > 0) {
			returnVo = new ReturnVo<>(ReturnCode.FAIL, "请先删除相关部门！");
		} else {
			LambdaQueryWrapper<Company> companyLambdaQueryWrapper = new LambdaQueryWrapper<>();
			companyLambdaQueryWrapper.eq(Company::getDelFlag, SysConstant.DEL_FLAG_1).eq(Company::getPid, ids.get(0));
			long companyCount = this.count(companyLambdaQueryWrapper);
			if (companyCount > 0) {
				returnVo = new ReturnVo<>(ReturnCode.FAIL, "该公司还有子公司，请确认！");
			} else {
				LambdaQueryWrapper<Company> deleteWrapper = new LambdaQueryWrapper<>();
				deleteWrapper.eq(Company::getDelFlag, SysConstant.DEL_FLAG_1).in(Company::getId, ids);
				this.deleteBatch(deleteWrapper);
			}
		}
		return returnVo;
	}

	@Override
	public List<OrgTreeVo> getCompanyTree(String keyword) {
		List<OrgTreeVo> orgTreeVos = new ArrayList<>();
		LambdaQueryWrapper<Company> companyLambdaQueryWrapper = new LambdaQueryWrapper<>();
		companyLambdaQueryWrapper.eq(Company::getStatus, 1).eq(Company::getDelFlag, SysConstant.DEL_FLAG_1);
		if (StringUtils.isNotBlank(keyword)) {
			companyLambdaQueryWrapper.like(Company::getCname, keyword).or().like(Company::getCode, keyword).or()
					.like(Company::getEname, keyword).or().like(Company::getShortName, keyword);
		}
		List<Company> companies = this.getList(companyLambdaQueryWrapper);
		if (CollectionUtils.isNotEmpty(companies)) {
			companies.forEach(company -> {
				OrgTreeVo orgTreeVo = new OrgTreeVo(company.getId(), company.getPid(), company.getCname(),
						company.getShortName(), OrgTreeVo.COMPANY_TYPE);
				orgTreeVo.setCode(company.getCode());
				orgTreeVos.add(orgTreeVo);
			});
		}
		return orgTreeVos;
	}

}